iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0

前兩天介紹的多半是概念性的內容,相信大家已經迫不及待看到程式碼了吧 ?所以今天會從 D03/static-pages的進度開始寫扣囉 `ヽ(\´▽`)/ `ヽ(´▽`)/ `ヽ(´▽`)/

資料夾結構簡介

  • 資料夾結構設計上我希望結合 Next.js 的資料夾路由MVC 概念,把對應 viewcomponents 和對應 modeldata 分清楚,所以我們會在 /components 同級目錄下新增 /data

  • 接著再新增一個 /addCourseForm 對應到 AddCourseForm component
    https://ithelp.ithome.com.tw/upload/images/20230921/20158615JWfvkQcuPG.png

  • 最後在 /addCourseForm 新增 textInput.ts

實作資料模型

開始前請先安裝 effect

npm i effect

現在請大家回想一下 D03 - 設計資料模型CourseName 還有 Description ,其實參考需求分析完畢後會發現格式根本一模一樣,所以我們可以把它歸納成一個 TextInput

import { Data, Equal } from 'effect'

export type TextInput = InitialTextInput | ValidTextInput | InvalidTextInput

export interface InitialTextInput extends Data.Case {
  readonly _tag: 'InitialTextInput'
  readonly value: ''
}

export interface ValidTextInput extends Data.Case {
  readonly _tag: 'ValidTextInput'
  readonly value: string
}
export interface InvalidTextInput extends Data.Case {
  readonly _tag: 'InvalidTextInput'
  readonly value: string
  readonly reason: string
}

上面範例擴展的的 Data.Case 可以讓原本不支援物件比對的 JS 物件,變得可以比對

import { Equal } from 'effect'

const result = Equal.equals(textInput1)(textInput)

更重要的是可以幫你產生 constructor

const ofValid = Data.tagged<ValidTextInput>('ValidTextInput')

const courseName1 = ofValid({ value: 'HTML/CSS/JS' })

測試驅動開發

行前準備

開始寫測試前再請大家裝個測試工具 vitest

npm i -D vitest

-Ddevelopment dependency 的意思,避免你在發布的時候包了不必要的開發工具

接著在 package.json 新增

  "scripts": {
    ...
    "test": "vitest"
    ...
  },

TDD 實用口訣

有時候我們很容易把 測試驅動開發 寫成 測試然後開發,要避免路越走越歪,關鍵就在於要把握以下原則

紅 綠 重構
紅 代表新增的功能還沒實作,所以肯定失敗
綠 代表新的的功能通過測試,但還有改進空間
重構 代表把通過測試的功能整理好

AAA
Arange 安排測資
Act 執行測試目標
Assert 驗證執行結果

需求回顧

https://ithelp.ithome.com.tw/upload/images/20230921/20158615N0EQEw11YL.png

type getInputString = (event:ChangeEvent) => string // 從輸入事件取出字串
type courseNameOf = (input:string) => CourseName // 把字串傳換成先前定義的資料模型

getInputString 沒有包含商業邏輯,就只是把字串拿出來而已,所以我們先不管它,先測courseNameOf,也就是現在的 textInputOf

開始寫測試!

原始碼請參考 D06/unit-test

  1. 在以下路徑新增 textInput.spect.ts 檔案
    https://ithelp.ithome.com.tw/upload/images/20230921/20158615QKSlz82R2f.png

  2. 把測試寫上去

    import { String } from 'effect'
    import { describe, expect, it } from 'vitest'
    
    describe('textInputOf', () => {
      const limit = { minLen: 1, maxLen: 50 }
    
      it('should be valid when input length is equal to min length', () => {
        const input = 'a' //arrange
        const result = textInputOf(limit)(input) //act
        expect(result._tag).toBe('ValidTextInput') //assert
      })
    
      it('should be valid when input length is equal to max length', () => {
        const input = String.repeat(50)('a')
        const result = textInputOf(limit)(input)
        expect(result._tag).toBe('ValidTextInput')
      })
    
      it('should be invalid when input length is greater than max length', () => {
        const input = String.repeat(51)('a')
        const result = textInputOf(limit)(input)
        expect(result._tag).toBe('InvalidTextInput')
      })
    
      it('should be invalid when input length is less than min length', () => {
        const input = ''
        const result = textInputOf(limit)(input)
        expect(result._tag).toBe('InvalidTextInput')
      })
    
      it('should be invalid when input includes chinese', () => {
        const input = '晚安 瑪卡巴卡'
        const result = textInputOf(limit)(input)
        expect(result._tag).toBe('InvalidTextInput')
      })
    
      it('should be invalid when input includes "!"', () => {
        const input = 'He110 w0r1d!'
        const result = textInputOf(limit)(input)
        expect(result._tag).toBe('InvalidTextInput')
      })
    })
    
  3. 打指令

    npm run test
    
  4. 紅燈 !
    https://ithelp.ithome.com.tw/upload/images/20230921/20158615CzErWQS6UB.png

  5. 加入長度驗證,大部分綠燈了 !
    https://ithelp.ithome.com.tw/upload/images/20230921/20158615IS1RdI7ajB.png

  6. 加入白名單驗證,全部綠燈 !

    https://ithelp.ithome.com.tw/upload/images/20230921/20158615fChu0JlLR8.png


Yes

時間已經很晚了,今天就先寫到這邊,大家晚安


上一篇
D05 - 設計工作流程
下一篇
D07 - 軌道導向設計
系列文
從 Next.js 開始的 Functional Programming30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言